package indi.defoliation.unknownrpg.api.lore;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import javax.annotation.Nonnull;

import com.google.common.base.Strings;

import indi.defoliation.unknownrpg.api.attribute.Attribute;
import indi.defoliation.unknownrpg.core.exception.AttributeAlreadyExistsException;

public class AttributeLoreManager {

	private static final TreeMap<String,Map<String,LoreFunction>> LORE_MAP = new TreeMap<>();

	private static final LoreSign CURLY_BRACKET = new LoreSign() {
		private static final String LEFT = "{";
		private static final String RIGHT = "}";
		private Map<String,LoreFunction> map;
		@Override
		public String getAfter() {
			return LEFT;
		}
		@Override
		public String getBefore() {
			return RIGHT;
		}
		@Override
		public String replace(final String lore) {
			int index;
			if((index=lore.indexOf("."))!=-1)
				map = AttributeLoreManager.getAttributeLore(lore.substring(0, index));
			else 
				map = AttributeLoreManager.getAttributeLore(lore);
			if(map!=null&&map.containsKey(lore))
				return map.get(lore).apply(lore);
			return "";
		}
	};

	private static final LoreSign ARROW_SIGN = new LoreSign() {
		private static final String LEFT = "<";
		private static final String RIGHT = ">";
		@Override
		public String getAfter() {
			return LEFT;
		}

		@Override
		public String getBefore() {
			return RIGHT;
		}

		@Override
		public String replace(final String lore) {
			if(lore.indexOf(CURLY_BRACKET.getBefore())==-1&&lore.indexOf(CURLY_BRACKET.getAfter())==-1)
				return lore;
			return "";
		}
	};

	public static void registe(@Nonnull final Attribute att,@Nonnull Map<String,LoreFunction> map) {
		if(LORE_MAP.containsKey(att.getKeyName()))
			throw new AttributeAlreadyExistsException(att.getKeyName()+"already exists");
		LORE_MAP.put(att.getKeyName(), map);
	}
	
	public static void unregiste(@Nonnull final Attribute att) {
		LORE_MAP.remove(att.getKeyName());
	}

	public static Map<String,LoreFunction> getAttributeLore(String attributeKeyName){
		return LORE_MAP.get(attributeKeyName);
	}

	public static List<String> replace(List<String> lore){
		lore = replace(lore,CURLY_BRACKET);
		return replace(lore,ARROW_SIGN);
	}

	public static List<String> replace(List<String> lore,final LoreSign sign){
		ArrayList<String> list = new ArrayList<>();
		lore.forEach((s)->{
			s = cutAndReplace(s,sign);
			if(!Strings.isNullOrEmpty(s))
				list.add(s);
		});
		return list;
	}

	private static String cutAndReplace(String str,final LoreSign sign) {
		ArrayList<String> list = new ArrayList<>();
		final String beforeSign = sign.getBefore();
		final String afterSign = sign.getAfter();
		int beforeIndex=-1;
		int afterIndex=0;
		while((beforeIndex=str.indexOf(beforeSign))!=-1) {
			afterIndex = str.indexOf(afterSign);
			if(afterIndex==-1)break;
			String keyWithSign =str.substring(beforeIndex, afterIndex+1);
			list.add(str.substring(0, beforeIndex));
			list.add(sign.replace(keyWithSign.substring(1,keyWithSign.length()-1)));
			str=str.substring(afterIndex+1);
		}
		if(list.isEmpty())return str;
		StringBuffer sb = new StringBuffer();
		list.forEach((s)->sb.append(s));
		return sb.toString();
	}
}
